/**
 * #### 文档标题生成快捷导航，不支持IE浏览器
 * @see https://www.zhangxinxu.com/study/202011/intersection-observer-title-nav.html
 * @param {HTMLElement[] | string} elements
 * @param {*} options
 * @returns
 */
function smartNav(elements, options) {
  // 定义默认选项
  const defaults = {
    nav: null,
  };
  // 将默认选项和传入的选项合并
  const params = Object.assign({}, defaults, options || {});
  // 如果传入的元素是字符串，则将其转换为元素节点
  if (typeof elements === "string") {
    elements = document.querySelectorAll(elements);
  }
  // 如果传入的元素没有forEach方法，则返回
  if (!elements.forEach) return;
  // 如果没有传入导航元素，则创建一个新的导航元素
  if (!params.nav) {
    params.nav = document.createElement("nav");
    params.nav.className = "title-nav-ul";
    document.body.appendChild(params.nav);
  }

  // 定义一个变量，记录上一次滚动位置
  let lastScrollTop = document.scrollingElement.scrollTop;
  // 创建一个IntersectionObserver对象，用于监听元素是否进入视口
  const ob = new IntersectionObserver((entries) => {
    // 如果设置了避免滚动，则返回
    if (params.isAvoid) return;
    // 将元素节点数组反转
    entries.reverse().forEach((entry) => {
      // 如果元素进入视口，则调用active方法
      if (entry.isIntersecting) {
        entry.target.active();
        // 如果元素离开视口，则调用unactive方法
      } else if (entry.target.isActived) {
        entry.target.unactive();
      }
    });
    // 更新上一次滚动位置
    lastScrollTop = document.scrollingElement.scrollTop;
  });

  // 遍历元素节点数组
  elements.forEach((ele, i) => {
    // 如果元素没有id属性，则生成一个随机id
    const id = ele.id || `smartNav${Math.random().toString().slice(2, 8)}`;
    ele.id = id;
    // 创建一个导航链接元素
    const eleNav = document.createElement("a");
    eleNav.href = `#${id}`;
    eleNav.className = "title-nav-li";
    eleNav.innerHTML = ele.textContent;
    // 将导航链接元素添加到导航元素中
    params.nav.appendChild(eleNav);
    // 添加active类，并设置isActived为true
    ele.active = function () {
      // 遍历eleNav的父元素下的所有active类元素，并将isActived设置为false，并移除active类
      eleNav.parentElement.querySelectorAll(".active").forEach((eleActive) => {
        ele.isActived = false;
        eleActive.classList.remove("active");
      });
      // 给ele添加active类，并设置isActived为true
      eleNav.classList.add("active");
      ele.isActived = true;
    };
    // 移除active类，并设置isActived为false
    ele.unactive = function () {
      // 如果页面滚动距离大于上一次滚动距离，则将下一个元素设置为active
      if (document.scrollingElement.scrollTop > lastScrollTop) {
        elements[i + 1] && elements[i + 1].active();
        // 否则将上一个元素设置为active
      } else {
        elements[i - 1] && elements[i - 1].active();
      }
      // 移除eleNav的active类，并设置isActived为false
      eleNav.classList.remove("active");
      ele.isActived = false;
    };
    // 监听ele的变化
    ob.observe(ele);
  });

  // 监听params.nav的点击事件
  params.nav.addEventListener("click", (e) => {
    // 获取点击的a标签
    const eleLink = e.target.closest("a");
    // 获取a标签的href属性对应的元素
    const eleTarget =
      eleLink && document.querySelector(eleLink.getAttribute("href"));
    // 如果eleTarget存在
    if (eleTarget) {
      // 阻止默认行为
      e.preventDefault();
      // 将eleTarget滚动到视窗中心
      eleTarget.scrollIntoView({ behavior: "smooth", block: "center" });

      // 如果浏览器支持scroll-behavior:smooth
      if (CSS.supports("scroll-behavior:smooth")) {
        // 设置isAvoid为true
        params.isAvoid = true;
        setTimeout(() => {
          eleTarget.active();
          params.isAvoid = false;
        }, Math.abs(eleTarget.getBoundingClientRect().top - window.innerHeight / 2) / 2);
      } else {
        eleTarget.active();
      }
    }
  });
}
